package com.ndp.fb.mq.service.publishhandleservice.post;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.targetingspec.Gender;
import com.ndp.fb.fbagent.service.AdCreativeFBService;
import com.ndp.fb.fbagent.service.AdGroupFBService;
import com.ndp.fb.model.business.bo.useraudience.result.FBTargetingSpecs;
import com.ndp.fb.model.fbagent.param.APIPriority;
import com.ndp.fb.model.fbagent.param.ApiCallBackTarget;
import com.ndp.fb.model.fbagent.param.adcreative.AdCreativeParam;
import com.ndp.fb.model.fbagent.param.adcreative.ChildAttachments;
import com.ndp.fb.model.fbagent.param.adcreative.ObjectStorySpec;
import com.ndp.fb.model.fbagent.param.adgroup.AdGroupParam;
import com.ndp.fb.model.fbagent.result.common.FBSingleId;
import com.ndp.fb.mongo.api.PublishCacheMongoService;
import com.ndp.fb.mq.api.service.publishhandleservice.PublishPostProcessor;
import com.ndp.fb.mq.api.service.publishhandleservice.PublishPostResult;
import com.ndp.fb.mq.service.schedulerservice.adpublish.PublishCacheMongoServiceFailover;
import com.ndp.fb.rdb.api.AdCreativeRdbService;
import com.ndp.fb.rdb.api.AdRdbService;
import com.ndp.fb.rdb.api.AdSetRdbService;
import com.ndp.fb.redis.model.AdCreativeLevel;
import com.ndp.fb.redis.model.AdGroupLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 外链广告发布完成后，进行外链地址的更新
 * Created by jacky.cheng on 2016/1/5.
 */
@Component
public class PublishPostUpdateCreativeForAd implements PublishPostProcessor {
    Logger logger = LoggerFactory.getLogger(getClass());

    @Reference
    AdCreativeFBService adCreativeFBService;

    @Reference
    AdCreativeRdbService adCreativeRdbService;
    @Reference
    AdSetRdbService adSetRdbService;
    @Reference
    AdRdbService adGroupRdbService;
    @Reference
    AdGroupFBService adGroupFBService;

    @Autowired
    private PublishCacheMongoServiceFailover publishCacheMongoService;

    @Override
    public void processor(PublishPostResult publishPostResult) {
        //外链广告发布完成后，更新link的占位符为adId,重新发布creative，更新Ad。
        AdGroupLevel adGroupLevel= (AdGroupLevel) publishPostResult.getBaseAdLevel();
        //只处理外链广告
        if (CommonConstants.OUTLINK.equalsIgnoreCase(adGroupLevel.getProductType())){
            try {
                logger.info("outLink ad post handler");
                createCreative(adGroupLevel,publishPostResult.getParatms());
            } catch (Exception e) {
                logger.error("outLink ad post handler error."+e);
            }
        }
    }

    private void createCreative(AdGroupLevel adGroupLevel, Map<String, String> params) {
        String adCreativeLevelStr=publishCacheMongoService.findCacheBlockByTypeAndKey(adGroupLevel.getPublishBatchId(),
                PublishCacheMongoService.CREATIVE,adGroupLevel.getAdCreativeBatchIndex());
        AdCreativeLevel adCreativeLevel= JSONObject.parseObject(adCreativeLevelStr,AdCreativeLevel.class);

        AdCreativeParam param = new AdCreativeParam();
        param.setObjectStorySpec(reBuildObjectStorySpec(adGroupLevel.getAdGroupId(),adGroupLevel.getName(),
                adGroupLevel.getTargeting(), adCreativeLevel.getObjectStorySpec()));
        param.setAccessToken(adCreativeLevel.getAccessToken());
        param.setFbAccountId(Long.parseLong(adCreativeLevel.getActAccountId().substring(4)));
        param.setApiPriorityCode(APIPriority.CreateAdCreative.getCode());
        param.setApiCallbackTargetType(ApiCallBackTarget.AdPublish.OutlinkAdCreative.getTargetType());
        param.setResultClass(FBSingleId.class);
        param.setUrlTags(reBuildUrlTags(adGroupLevel.getAdGroupId(), adCreativeLevel.getUrlTags()));
        param.setCallBack(true);
        param.setProductSetId(adCreativeLevel.getProductSetId());
        //需要回调传递的参数
        HashMap<String, String> equip = new HashMap<>();
        equip.put("adGroupId", adGroupLevel.getAdGroupId());
        equip.put("adCreativeId", adGroupLevel.getAdCreativeId()+"");
        equip.put("fbAccountId",param.getFbAccountId()+"");
        equip.put("token", adGroupLevel.getAccessToken());
        param.setEquipment(equip);
        adCreativeFBService.createAdCreative(param);
    }
    private String reBuildUrlTags(String adGroupId,String url_tags){
    	url_tags = url_tags+"_wallead-"+adGroupId;
    	return url_tags;
    }
    private ObjectStorySpec reBuildObjectStorySpec(String adGroupId,String adgroupName, Object targeting, ObjectStorySpec objectStorySpec) {
        //创意objectStorySpec属性，翻转后的对象
        ObjectStorySpec oosParam = objectStorySpec;
        FBTargetingSpecs targetingSpecs=JSON.parseObject(targeting.toString(),FBTargetingSpecs.class);

        String link;
        if (oosParam.getLinkData() != null) {
            //图片
            link = oosParam.getLinkData().getLink();
            link = reBuildLink(adGroupId,adgroupName, link, targetingSpecs);
            oosParam.getLinkData().setLink(link);
            if (oosParam.getLinkData().getCallToAction() != null) {
                oosParam.getLinkData().getCallToAction().getValue().setLink(link);
            }
            //轮播
            if (oosParam.getLinkData().getChildAttachmentses() != null) {
                for (ChildAttachments childAttachments : oosParam.getLinkData().getChildAttachmentses()) {
                    childAttachments.setLink(link);
                    if (childAttachments.getCallToAction() != null && childAttachments.getCallToAction().getValue() != null){
                        childAttachments.getCallToAction().getValue().setLink(link);
                    }
                }
            }
        }
        //视频
        if (oosParam.getVideoData()!=null){
            if (oosParam.getVideoData().getCallToAction() != null) {
                link = oosParam.getVideoData().getCallToAction().getValue().getLink();
                link = reBuildLink(adGroupId,adgroupName,link ,targetingSpecs);
                oosParam.getVideoData().getCallToAction().getValue().setLink(link);
            }
        }
        //视频
        if (oosParam.getTemplateData()!=null){
            if (oosParam.getTemplateData().getLink()!=null) {
                link = oosParam.getTemplateData().getLink();
                link = reBuildLink(adGroupId,adgroupName,link ,targetingSpecs);
                oosParam.getTemplateData().setLink(link);
            }
        }

        return oosParam;
    }

    private String reBuildLink(String adGroupId, String adgroupName,String link, FBTargetingSpecs targetingSpecs) {
    	if(!link.contains("?")){
    		link = link+"?";
    	}
      //  AdGroup adGroup = adGroupRdbService.findByAdGroupId(Long.valueOf(adGroupId));
        String genderStr = linkWithUnderScore(parseGender(targetingSpecs.getGenders()), "_");
        String countryStr = linkWithUnderScore(targetingSpecs.getGeoLocations().getCountries(), "_");
        String age =  targetingSpecs.getAgeMin() + "_" + targetingSpecs.getAgeMax();
        link=link.replace("_adGroupId_", adGroupId);
        link=link.replace("_COUNTRY_", countryStr);
        link=link.replace("_GENDER_", genderStr);
        link=link.replace("_AGE_", age);
        //append sub2=adGroupName
        link = link.endsWith("?")?(link+"sub2=" + adgroupName):(link + "&sub2=" + adgroupName);
        return link;
    }

    private List<String> parseGender(List<Integer> genders){
        List<String> genderLs = new ArrayList<>();
        if (CollectionUtils.isEmpty(genders)){
            genderLs.add("F");
            genderLs.add("M");
        } else {
            for (Integer gender : genders){
                if (Gender.male.getCode() == gender) {
                    genderLs.add("M");
                } else if(Gender.all.getCode() == gender) {
                    genderLs.add("F");
                    genderLs.add("M");
                } else {
                    genderLs.add("F");
                }
            }
        }
        return genderLs;
    }

    private String linkWithUnderScore(List<String> list, String line) {
        StringBuffer sb = new StringBuffer();
        boolean isFirst = true;
        for (String s : list) {
            if (!isFirst){
                sb.append(line);
            }
            sb.append(s);
            isFirst = false;
        }
        return sb.toString();
    }

    /**
     * 外链广告创意创建回调
     * @param equipment
     * @param fbSingleId
     */
    public void createCreativeCallBack(Map<String, String> equipment, Object fbSingleId){
        if (fbSingleId instanceof FBSingleId) {
        	logger.info("外链广告创建创意成功");
            Long adCreativeId;
            adCreativeId = ((FBSingleId) fbSingleId).getId();
            String adGroupId = equipment.get("adGroupId");
            Long fbAccountId=Long.valueOf(equipment.get("fbAccountId"));
            String token = equipment.get("token");
            updateCreateForAd(adGroupId,adCreativeId,fbAccountId , token);
        }else{
        	logger.info("外链广告创建创意失败");
        	logger.error(fbSingleId.toString());
        }
    }
    private void updateCreateForAd(String adGroupId, Long creativeId, Long actId, String token) {
        AdGroupParam param=new AdGroupParam();
        param.setAdGroupId(adGroupId);
        param.setCreative("{'creative_id': "+creativeId+"}");
        param.setFbAccountId(actId);
        param.setAccessToken(token);
        //使用暂停广告的优先级 ，因为都属于修改业务数据，这个是异步返回
        param.setApiPriorityCode(APIPriority.PauseAdGroup.getCode());
        param.setApiCallbackTargetType(ApiCallBackTarget.AdPublish.OutlinkAdGroup.getTargetType());
        param.setCallBack(true);
        HashMap<String, String> equip = new HashMap<>();
        equip.put("adGroupId", adGroupId);
        equip.put("adCreativeId", creativeId+"");
        param.setEquipment(equip);
        adGroupFBService.updateAdGroupStats(param);
    }

    /**
     * 更新adGroup回调
     * @param equipment
     * @param message
     */
    public void updateAdGroupCallBack(Map<String, String> equipment, Object message) {
        Boolean success = (Boolean) JSON.parseObject(message.toString()).get("success");
        if (!success) {
            logger.error("update creative for ad failed. adId:{},creativeId:{}",equipment.get("adGroupId"),equipment.get("adCreativeId"));
            return;
        }
        adGroupRdbService.updateAdCreativeId(Long.valueOf(equipment.get("adGroupId")), Long.valueOf(equipment.get("adCreativeId")));
    }
}
